#![allow(dead_code)]

use rand::Rng;
use rand::distr::{Alphanumeric, Distribution, StandardUniform, Uniform};
use rand::seq::{IndexedRandom, SliceRandom};

/// 随机生成一个数
fn rand_number() {
    let mut rng = rand::rng();

    let n1: u8 = rng.random();
    let n2: u16 = rng.random();
    println!("Random u8: {}", n1);
    println!("Random u16: {}", n2);
    println!("Random u32: {}", rng.random::<u32>());
    println!("Random i32: {}", rng.random::<i32>());
    // 生成浮点数
    println!("Random float: {}", rng.random::<f64>());
    // 生成一个1..10内的数
    println!("Random range: {}", rng.random_range(1..10));
}

/// 生成均匀分布的值
/// 与rng.gen_range(1..10)具有相同的效果，
/// 但在相同范围内重复生成数字时，下述代码性能可能会更好。
fn rand_uniform() {
    let mut rng = rand::rng();
    let die = Uniform::new(1, 10).unwrap();

    loop {
        let throw = die.sample(&mut rng);
        println!("Roll the die: {}", throw);
        if throw == 6 {
            break;
        }
    }
}

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

impl Distribution<Point> for StandardUniform {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
        let (x, y) = rng.random();
        Point { x, y }
    }
}

/// 随机用户定义类型为 Point 的变量
fn rand_point() {
    let mut rng = rand::rng();
    // 随机生成一个元组
    let rand_tuple = rng.random::<(i32, bool, f64)>();
    // 随机生成一个Point
    let rand_point: Point = rng.random();
    println!("Random tuple: {:?}", rand_tuple);
    println!("Random Point: {:?}", rand_point);
}

/// 从一组字母数字字符创建随机密码
fn rand_string1() {
    let rand_string: String = rand::rng()
        // 采样的字符串
        .sample_iter(&Alphanumeric)
        // 字符串长度
        .take(10)
        .map(char::from)
        .collect();

    println!("{}", rand_string);
}

/// 从一组字母数字字符创建随机密码
fn rand_string2() {
    const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                            abcdefghijklmnopqrstuvwxyz\
                            0123456789\
                            *&#@!.";
    const PASSWORD_LEN: usize = 10;
    let mut rng = rand::rng();

    let password: String = (0..PASSWORD_LEN)
        .map(|_| {
            let idx = rng.random_range(0..CHARSET.len());
            CHARSET[idx] as char
        })
        .collect();

    println!("{:?}", password);
}

/// 将一个vec打乱顺序随机选择一个
fn choose(){
    let mut rng = rand::rng();
    // Generate and shuffle a sequence:
    let mut nums: Vec<i32> = (1..100).collect();
    nums.shuffle(&mut rng);
    // And take a random pick (yes, we didn't need to shuffle first!):
    let random = nums.choose(&mut rng).unwrap();
    println!("{:?}", random);
}
fn main() {
    choose()
}
